// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

/*
 * @Author: qiulin_JXGM ql1746365080@gmail.com
 * @Date: 2024-12-07 20:32:49
 * @LastEditors: qiulin 1746365080@qq.com
 * @LastEditTime: 2025-01-02 17:05:31
 * @FilePath: \SGSim\Import\BDFImport\BulkData\Dynamic\EIGCParser.cpp
 */

#include "EIGCParser.h"

#include <cstdint>
#include <iostream>

#include "boost/algorithm/string.hpp"

#include "Utility/Logging/SGLogger.h"

#include "DBManager/DBServiceFactory.h"
#include "DBManager/IService/Input/Dynamic/IEIGCService.h"

#include "Import/BDFImport/BDFImport.h"
#include "Import/BDFImport/BDFParserBase.h"
BULKDATA_ENTRY_PARSER_REG (EIGC);

using namespace SG::DBManager;
using namespace SG::Import;
using namespace SG::Import::BDF;
using namespace SG::DataStructure;
/*
// file://./../../Doc/MarkDown/BulkData/EIGC/EIGC.md>
*/
// 以下需要修改
enum EIGCFirstIndex : std::uint8_t
{
    EIGCFirstIndex_SID    = 1,
    EIGCFirstIndex_METHOD = 2,  // 复特征值提取方法。（字符：“INV”，“HESS”或“CLAN”）
    EIGCFirstIndex_NORM   = 3,  // 用于特征向量归一化的方法。参见备注 7。（字符：“MAX” 或 “POINT”；默认 = “MAX”）
    EIGCFirstIndex_G      = 4,  // 网格或标量点的标识号。当且仅当 NORM = "POINT" 时需要。
    EIGCFirstIndex_C      = 5,  // 分量号。当且仅当 NORM="POINT" 且 G 是几何网格点时需要。（0 ≤ 整数 ≤ 6）
    EIGCFirstIndex_E =
        6,  // 收敛准则。（实数 ≥ 0.0。默认值：METHOD 为 "INV" 时为 1E-4，METHOD 为 "HESS" 时为 1E-5，METHOD 为 "CLAN" 时 E 取决于机器）
    EIGCFirstIndex_ND0 = 7
};

//  HESS方法仅使用NDJ，以下注释仅针对INV
enum EIGCSecondIndex : std::uint8_t
{
    EIGCSecondIndex_ALPHAAJ = 1,  // Real and imaginary parts of Aj in radians per unit time.
                                  // End point Aj of j-th search region in complex plane. (Default = 0.0)
    EIGCSecondIndex_OMEGAAJ = 2,
    EIGCSecondIndex_ALPHABJ = 3,  // Real and imaginary parts of Bj in radians per unit time.
                                  // End point Bj of j-th search region in complex plane. (Default = 0.0)
    EIGCSecondIndex_OMEGABJ = 4,
    EIGCSecondIndex_LJ      = 5,  // Width of j-th search region.(Default = 1.0)
    EIGCSecondIndex_NEJ     = 6,  // Estimated number of roots in j-th search region.
    EIGCSecondIndex_NDJ     = 7,  // Desired number of roots and eigenvectors in j-th search region. (Default = 3*NEj)
};

// enum EIGCSecondIndexLanczos : std::uint8_t
// {
//     EIGCSecondIndexLanczos_ALPHAAJ = 1,  // J-th  shift point  ,AJ的实部与虚部部分，理解为频率感兴趣的起始点
//     EIGCSecondIndexLanczos_OMEGAAJ = 2,
//     EIGCSecondIndexLanczos_MBLKSZ  = 3,  // 最大块大小。参见备注 11。（默认值 = 7；实数 ≥ 0.0）
//     EIGCSecondIndexLanczos_IBLKSZ  = 4,  // 初始块大小。参见备注 11。（默认值 = 2；实数 ≥ 0.0）
//     EIGCSecondIndexLanczos_KSTEPS  = 5,  // 求解频率。（默认值 = 5；整数 > 0）
//     EIGCSecondIndexLanczos_NJI     = 7,
// };

namespace
{

    void ParseFirstLine (std::vector<std::string>& dividedEntryInfo, SG::DataStructure::FEM::EIGCData& tempEIGC)
    {
        for (size_t i = 1; i < 8; i++)
        {
            boost::trim (dividedEntryInfo[i]);
            boost::to_upper (dividedEntryInfo[i]);
            switch (i)
            {
            case EIGCFirstIndex_SID:
                tempEIGC.m_sId = convertToI64 (dividedEntryInfo[i]);
                break;
            case EIGCFirstIndex_METHOD:
                std::strncpy (tempEIGC.m_METHOD,
                              boost::algorithm::trim_copy (dividedEntryInfo[i]).c_str (),
                              boost::algorithm::trim_copy (dividedEntryInfo[i]).size ());
                switch (tempEIGC.m_METHOD[1])
                {
                // TODO(bug 001) 其他方法默认值暂时给1.0E-8.与H5一致
                case 'N':
                    tempEIGC.m_E = 1E-8;
                    break;
                case 'E':
                    tempEIGC.m_E = 1E-8;
                    break;

                case 'L':
                case 'R':
                default:
                    tempEIGC.m_E = 1.0E-8;

                    break;
                }
                break;
            case EIGCFirstIndex_NORM:
                if (dividedEntryInfo[i] == "")
                {
                    dividedEntryInfo[i] = "MAX";
                }
                std::strncpy (tempEIGC.m_NORM,
                              boost::algorithm::trim_copy (dividedEntryInfo[i]).c_str (),
                              boost::algorithm::trim_copy (dividedEntryInfo[i]).size ());
                break;
            case EIGCFirstIndex_G:
                if (dividedEntryInfo[i] != "")
                {
                    tempEIGC.m_G = convertToI64 (dividedEntryInfo[i]);
                }
                break;
            case EIGCFirstIndex_C:
                if (dividedEntryInfo[i] != "")
                {
                    tempEIGC.m_C = convertToI64 (dividedEntryInfo[i]);
                }
                break;
            case EIGCFirstIndex_E:
                if (dividedEntryInfo[i] != "")
                {
                    tempEIGC.m_E = convertToReal (dividedEntryInfo[i]);
                }
                break;
            case EIGCFirstIndex_ND0:
                if (dividedEntryInfo[i] != "")
                {
                    tempEIGC.m_ND1 = convertToReal (dividedEntryInfo[i]);
                }
                break;
            default:
                break;
            }
        }
    }

    void ParseSecond (std::vector<std::string>& dividedEntryInfo, SG::DataStructure::FEM::EIGCData& tempEIGC)
    {
        size_t rowNum = dividedEntryInfo.size () / 10;
        tempEIGC.m_REGIONList.clear ();
        tempEIGC.m_REGIONList.resize (rowNum - 1);
        // 遍历每一行词条，处理维度信息
        for (size_t curRow = 1; curRow < rowNum; curRow++)
        {
            // 遍历每行中的字段
            for (size_t fieldsColumn = 1; fieldsColumn < 9; fieldsColumn++)
            {
                // 计算当前字段在dividedEntryInfo中的索引
                const size_t curIndex  = curRow * 10 + fieldsColumn;
                std::string& curStrKey = dividedEntryInfo[curIndex];
                boost::trim (curStrKey);
                switch (fieldsColumn)
                {
                case EIGCSecondIndex_ALPHAAJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_AAJ = convertToReal (curStrKey);
                    }
                    break;
                case EIGCSecondIndex_OMEGAAJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_WAJ = convertToReal (curStrKey);
                    }
                    break;
                case EIGCSecondIndex_ALPHABJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_ABJ = convertToReal (curStrKey);
                    }
                    // TODO(bug 001) CLAN默认的black h5未给，默认值为赋予
                    break;
                case EIGCSecondIndex_OMEGABJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_WBJ = convertToReal (curStrKey);
                    }
                    // TODO(bug 001) CLAN默认的black h5未给，默认值为赋予
                    break;
                case EIGCSecondIndex_LJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_LJ = convertToReal (curStrKey);
                    }
                    // 对于INV方法m_LJ 默认为1.0
                    else
                    {
                        if (tempEIGC.m_METHOD[1] == 'N')
                        {
                            tempEIGC.m_REGIONList[curRow - 1].m_LJ = 1.0;
                        }
                    }
                    // TODO(bug 001) CLAN默认的black h5未给，默认值为赋予
                    break;
                case EIGCSecondIndex_NEJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_NEJ = convertToReal (curStrKey);
                        // 对于INV方法m_NDJ 默认为3*m_NEJ
                        // TODO(bug 001) H5中是0
                        if (tempEIGC.m_METHOD[1] == 'N')
                        {
                            tempEIGC.m_REGIONList[curRow - 1].m_NDJ = 3 * tempEIGC.m_REGIONList[curRow - 1].m_NEJ;
                        }
                    }
                    break;
                case EIGCSecondIndex_NDJ:
                    if (curStrKey != "")
                    {
                        tempEIGC.m_REGIONList[curRow - 1].m_NDJ = convertToReal (curStrKey);
                    }
                    break;
                default:
                    break;
                }
            }
        }
    }

}  // namespace
SG::DataStructure::Common::Status BDF::BULKDATA::ParseEIGC (const std::shared_ptr<SG::DBManager::DBServiceFactory>& dbServiceFactory,
                                                            std::vector<std::string>&                               dividedEntryInfo)
{
    SG::DataStructure::FEM::EIGCData tempEIGC;  // 创建一个临时EIGC数据对象

    // TODO(bug 001) m_dominId的正确填写
    tempEIGC.m_domainId = 1;  // 暂时将m_domainId设为1，待修复

    ParseFirstLine (dividedEntryInfo, tempEIGC);
    ParseSecond (dividedEntryInfo, tempEIGC);
    // 将解析后的EIGC数据添加到数据库中
    return dbServiceFactory->get<IEIGCService> ()->Add (tempEIGC);
}